/*******************************************************************************
  MPLAB Harmony Application Source File
  
  Company:
    Microchip Technology Inc.
  
  File Name:
    app.c

  Summary:
    This file contains the source code for the MPLAB Harmony application.

  Description:
    This file contains the source code for the MPLAB Harmony application.  It 
    implements the logic of the application's state machine and it may call 
    API routines of other MPLAB Harmony modules in the system, such as drivers,
    system services, and middleware.  However, it does not call any of the
    system interfaces (such as the "Initialize" and "Tasks" functions) of any of
    the modules in the system or make any assumptions about when those functions
    are called.  That is the responsibility of the configuration-specific system
    files.
 *******************************************************************************/

// DOM-IGNORE-BEGIN
/*******************************************************************************
Copyright (c) 2013-2014 released Microchip Technology Inc.  All rights reserved.

Microchip licenses to you the right to use, modify, copy and distribute
Software only when embedded on a Microchip microcontroller or digital signal
controller that is integrated into your product or third party product
(pursuant to the sublicense terms in the accompanying license agreement).

You should refer to the license agreement accompanying this Software for
additional information regarding your rights and obligations.

SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE.
IN NO EVENT SHALL MICROCHIP OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER
CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR
OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR
CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT OF
SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
(INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
 *******************************************************************************/
// DOM-IGNORE-END


// *****************************************************************************
// *****************************************************************************
// Section: Included Files 
// *****************************************************************************
// *****************************************************************************

#include "app.h"
#include "PS2Keyboard.h"
#include "KeyTranslator.h"

// *****************************************************************************
// *****************************************************************************
// Section: Global Data Definitions
// *****************************************************************************
// *****************************************************************************

// *****************************************************************************
/* Application Data

  Summary:
    Holds application data

  Description:
    This structure holds the application's data.

  Remarks:
    This structure should be initialized by the APP_Initialize function.
    
    Application strings and buffers are be defined outside this structure.
*/

APP_DATA appData;

/*Keyboard Report to be transmitted*/
KEYBOARD_INPUT_REPORT APP_MAKE_BUFFER_DMA_READY keyboardInputReport;
/* Keyboard output report */
KEYBOARD_OUTPUT_REPORT APP_MAKE_BUFFER_DMA_READY keyboardOutputReport;

uint8_t americanKeyboard[] = {
	0x10, 0x04, 0x1C, 0x00, 0x00, 0xF0, 0x1C, 0x00,    //a A
	0x10, 0x05, 0x32, 0x00, 0x00, 0xF0, 0x32, 0x00,    //b B
	0x10, 0x06, 0x21, 0x00, 0x00, 0xF0, 0x21, 0x00,    //c C
	0x10, 0x07, 0x23, 0x00, 0x00, 0xF0, 0x23, 0x00,    //d D
	0x10, 0x08, 0x24, 0x00, 0x00, 0xF0, 0x24, 0x00,    //e E
	0x10, 0x09, 0x2B, 0x00, 0x00, 0xF0, 0x2B, 0x00,    //f F
	0x10, 0x0A, 0x34, 0x00, 0x00, 0xF0, 0x34, 0x00,    //g G
	0x10, 0x0B, 0x33, 0x00, 0x00, 0xF0, 0x33, 0x00,    //h H
	0x10, 0x0C, 0x43, 0x00, 0x00, 0xF0, 0x43, 0x00,    //i I
	0x10, 0x0D, 0x3B, 0x00, 0x00, 0xF0, 0x3B, 0x00,    //j J
	0x10, 0x0E, 0x42, 0x00, 0x00, 0xF0, 0x42, 0x00,    //k K
	0x10, 0x0F, 0x4B, 0x00, 0x00, 0xF0, 0x4B, 0x00,    //l L
	0x10, 0x10, 0x3A, 0x00, 0x00, 0xF0, 0x3A, 0x00,    //m M
	0x10, 0x11, 0x31, 0x00, 0x00, 0xF0, 0x31, 0x00,    //n N
	0x10, 0x12, 0x44, 0x00, 0x00, 0xF0, 0x44, 0x00,    //o O
	0x10, 0x13, 0x4D, 0x00, 0x00, 0xF0, 0x4D, 0x00,    //p P
	0x10, 0x14, 0x15, 0x00, 0x00, 0xF0, 0x15, 0x00,    //q Q
	0x10, 0x15, 0x2D, 0x00, 0x00, 0xF0, 0x2D, 0x00,    //r R
	0x10, 0x16, 0x1B, 0x00, 0x00, 0xF0, 0x1B, 0x00,    //s S
	0x10, 0x17, 0x2C, 0x00, 0x00, 0xF0, 0x2C, 0x00,    //t T
	0x10, 0x18, 0x3C, 0x00, 0x00, 0xF0, 0x3C, 0x00,    //u U
	0x10, 0x19, 0x2A, 0x00, 0x00, 0xF0, 0x2A, 0x00,    //v V
	0x10, 0x1A, 0x1D, 0x00, 0x00, 0xF0, 0x1D, 0x00,    //w W
	0x10, 0x1B, 0x22, 0x00, 0x00, 0xF0, 0x22, 0x00,    //x X
	0x10, 0x1C, 0x35, 0x00, 0x00, 0xF0, 0x35, 0x00,    //y Y
	0x10, 0x1D, 0x1A, 0x00, 0x00, 0xF0, 0x1A, 0x00,    //z Z
	0x10, 0x1E, 0x16, 0x00, 0x00, 0xF0, 0x16, 0x00,    //1 !
	0x10, 0x1F, 0x1E, 0x00, 0x00, 0xF0, 0x1E, 0x00,    //2 @
	0x10, 0x20, 0x26, 0x00, 0x00, 0xF0, 0x26, 0x00,    //3 #
	0x10, 0x21, 0x25, 0x00, 0x00, 0xF0, 0x25, 0x00,    //4 $
	0x10, 0x22, 0x2E, 0x00, 0x00, 0xF0, 0x2E, 0x00,    //5 %
	0x10, 0x23, 0x36, 0x00, 0x00, 0xF0, 0x36, 0x00,    //6 ^
	0x10, 0x24, 0x3D, 0x00, 0x00, 0xF0, 0x3D, 0x00,    //7 &
	0x10, 0x25, 0x3E, 0x00, 0x00, 0xF0, 0x3E, 0x00,    //8 *
	0x10, 0x26, 0x46, 0x00, 0x00, 0xF0, 0x46, 0x00,    //9 (
	0x10, 0x27, 0x45, 0x00, 0x00, 0xF0, 0x45, 0x00,    //0 )
	0x10, 0x28, 0x5A, 0x00, 0x00, 0xF0, 0x5A, 0x00,    //Return
	0x10, 0x29, 0x76, 0x00, 0x00, 0xF0, 0x76, 0x00,    //Escape
	0x10, 0x2A, 0x66, 0x00, 0x00, 0xF0, 0x66, 0x00,    //Backspace
	0x10, 0x2B, 0x0D, 0x00, 0x00, 0xF0, 0x0D, 0x00,    //Tab
	0x10, 0x2C, 0x29, 0x00, 0x00, 0xF0, 0x29, 0x00,    //Space
	0x10, 0x2D, 0x4E, 0x00, 0x00, 0xF0, 0x4E, 0x00,    //- _
	0x10, 0x2E, 0x55, 0x00, 0x00, 0xF0, 0x55, 0x00,    //= +
	0x10, 0x2F, 0x54, 0x00, 0x00, 0xF0, 0x54, 0x00,    //[ {
	0x10, 0x30, 0x5B, 0x00, 0x00, 0xF0, 0x5B, 0x00,    //] }
	0x10, 0x31, 0x5D, 0x00, 0x00, 0xF0, 0x5D, 0x00,    //\ |
	0x10, 0x33, 0x4C, 0x00, 0x00, 0xF0, 0x4C, 0x00,    //; :
	0x10, 0x34, 0x52, 0x00, 0x00, 0xF0, 0x52, 0x00,    //' "
	0x10, 0x35, 0x0E, 0x00, 0x00, 0xF0, 0x0E, 0x00,    //` ~
	0x10, 0x36, 0x41, 0x00, 0x00, 0xF0, 0x41, 0x00,    //, <
	0x10, 0x37, 0x49, 0x00, 0x00, 0xF0, 0x49, 0x00,    //. >
	0x10, 0x38, 0x4A, 0x00, 0x00, 0xF0, 0x4A, 0x00,    /// ?
	0x10, 0x39, 0x58, 0x00, 0x00, 0xF0, 0x58, 0x00,    //Caps Lock
	0x10, 0x3A, 0x05, 0x00, 0x00, 0xF0, 0x05, 0x00,    //F1
	0x10, 0x3B, 0x06, 0x00, 0x00, 0xF0, 0x06, 0x00,    //F2
	0x10, 0x3C, 0x04, 0x00, 0x00, 0xF0, 0x04, 0x00,    //F3
	0x10, 0x3D, 0x0C, 0x00, 0x00, 0xF0, 0x0C, 0x00,    //F4
	0x10, 0x3E, 0x03, 0x00, 0x00, 0xF0, 0x03, 0x00,    //F5
	0x10, 0x3F, 0x0B, 0x00, 0x00, 0xF0, 0x0B, 0x00,    //F6
	0x10, 0x40, 0x83, 0x00, 0x00, 0xF0, 0x83, 0x00,    //F7
	0x10, 0x41, 0x0A, 0x00, 0x00, 0xF0, 0x0A, 0x00,    //F8
	0x10, 0x42, 0x01, 0x00, 0x00, 0xF0, 0x01, 0x00,    //F9
	0x10, 0x43, 0x09, 0x00, 0x00, 0xF0, 0x09, 0x00,    //F10
	0x10, 0x44, 0x78, 0x00, 0x00, 0xF0, 0x78, 0x00,    //F11
	0x10, 0x45, 0x07, 0x00, 0x00, 0xF0, 0x07, 0x00,    //F12
	0x10, 0x46, 0xE0, 0x7C, 0x00, 0xE0, 0xF0, 0x7C,    //Print Screen
	0x10, 0x47, 0x7E, 0x00, 0x00, 0xF0, 0x7E, 0x00,    //Scroll Lock
	0x10, 0x49, 0xE0, 0x70, 0x00, 0xE0, 0xF0, 0x70,    //Insert
	0x10, 0x4A, 0xE0, 0x6C, 0x00, 0xE0, 0xF0, 0x6C,    //Home
	0x10, 0x4B, 0xE0, 0x7D, 0x00, 0xE0, 0xF0, 0x7D,    //Page Up
	0x10, 0x4C, 0xE0, 0x71, 0x00, 0xE0, 0xF0, 0x71,    //Delete
	0x10, 0x4D, 0xE0, 0x69, 0x00, 0xE0, 0xF0, 0x69,    //End
	0x10, 0x4E, 0xE0, 0x7A, 0x00, 0xE0, 0xF0, 0x7A,    //Page Down
	0x10, 0x4F, 0xE0, 0x74, 0x00, 0xE0, 0xF0, 0x74,    //Right Arrow
	0x10, 0x50, 0xE0, 0x6B, 0x00, 0xE0, 0xF0, 0x6B,    //Left Arrow
	0x10, 0x51, 0xE0, 0x72, 0x00, 0xE0, 0xF0, 0x72,    //Down Arrow
	0x10, 0x52, 0xE0, 0x75, 0x00, 0xE0, 0xF0, 0x75,    //Up Arrow
	0x10, 0x53, 0xE0, 0x9C, 0x00, 0xE0, 0xF0, 0x9C,    //Keypad Enter
	0x10, 0x54, 0xE0, 0xB5, 0x00, 0xE0, 0xF0, 0xB5,    //Keypad /
	0x10, 0x55, 0x77, 0x00, 0x00, 0xF0, 0x77, 0x00,    //Num Lock
	0x10, 0x56, 0x7C, 0x00, 0x00, 0xF0, 0x7C, 0x00,    //Keypad *
	0x10, 0x57, 0x7B, 0x00, 0x00, 0xF0, 0x7B, 0x00,    //Keypad -
	0x10, 0x58, 0x79, 0x00, 0x00, 0xF0, 0x79, 0x00,    //Keypad +
	0x10, 0x59, 0x69, 0x00, 0x00, 0xF0, 0x69, 0x00,    //Keypad 1 End
	0x10, 0x5A, 0x72, 0x00, 0x00, 0xF0, 0x72, 0x00,    //Keypad 2 Down
	0x10, 0x5B, 0x7A, 0x00, 0x00, 0xF0, 0x7A, 0x00,    //Keypad 3 PageDn
	0x10, 0x5C, 0x6B, 0x00, 0x00, 0xF0, 0x6B, 0x00,    //Keypad 4 Left
	0x10, 0x5D, 0x73, 0x00, 0x00, 0xF0, 0x73, 0x00,    //Keypad 5
	0x10, 0x5E, 0x74, 0x00, 0x00, 0xF0, 0x74, 0x00,    //Keypad 6 Right
	0x10, 0x5F, 0x6C, 0x00, 0x00, 0xF0, 0x6C, 0x00,    //Keypad 7 Home
	0x10, 0x60, 0x75, 0x00, 0x00, 0xF0, 0x75, 0x00,    //Keypad 8 Up
	0x10, 0x61, 0x7D, 0x00, 0x00, 0xF0, 0x7D, 0x00,    //Keypad 9 PageUp
	0x10, 0x62, 0x70, 0x00, 0x00, 0xF0, 0x70, 0x00,    //Keypad 0 Insert
	0x10, 0x63, 0x71, 0x00, 0x00, 0xF0, 0x71, 0x00,    //Keypad . Delete
	0x10, 0xE0, 0x14, 0x00, 0x00, 0xF0, 0x14, 0x00,    //Left Control
	0x10, 0xE1, 0x12, 0x00, 0x00, 0xF0, 0x12, 0x00,    //Left Shift
	0x10, 0xE2, 0x11, 0x00, 0x00, 0xF0, 0x11, 0x00,    //Left Alt
	0x10, 0xE3, 0xE0, 0x1F, 0x00, 0xE0, 0xF0, 0x1F,    //Left GUI
	0x10, 0xE4, 0xE0, 0x14, 0x00, 0xE0, 0xF0, 0x14,    //Right Control
	0x10, 0xE5, 0x59, 0x00, 0x00, 0xF0, 0x59, 0x00,    //Right Shift
	0x10, 0xE6, 0xE0, 0x11, 0x00, 0xE0, 0xF0, 0x11,    //Right Alt
	0x10, 0xE7, 0xE0, 0x27, 0x00, 0xE0, 0xF0, 0x27,    //Right GUI
};


// *****************************************************************************
// *****************************************************************************
// Section: Application Callback Functions
// *****************************************************************************
// *****************************************************************************

void PS2_Keyboard_Int(unsigned char code1, unsigned char code2, unsigned char code3){
    Translate(appData.keyboard_id,code1,code2,code3);
}

void Translated_Key(uint16_t code){

    // Check for modifier keys
    bool modifier = true;
    uint8_t modifier_bit = 0;
    if ((KEY_RELEASE & code) != KEY_RELEASE ) modifier_bit = 1;
    switch (code & 0xff){
        case USB_HID_KEYBOARD_KEYPAD_KEYBOARD_LEFT_CONTROL:
            appData.keyboardModifierKeys.leftCtrl = modifier_bit;
            break;
        case USB_HID_KEYBOARD_KEYPAD_KEYBOARD_LEFT_SHIFT:
            appData.keyboardModifierKeys.leftShift = modifier_bit;
            break;
        case USB_HID_KEYBOARD_KEYPAD_KEYBOARD_LEFT_ALT:
            appData.keyboardModifierKeys.leftAlt = modifier_bit;
            break;
        case USB_HID_KEYBOARD_KEYPAD_KEYBOARD_LEFT_GUI:
            appData.keyboardModifierKeys.leftGui = modifier_bit;
            break;
        case USB_HID_KEYBOARD_KEYPAD_KEYBOARD_RIGHT_CONTROL:
            appData.keyboardModifierKeys.rightCtrl = modifier_bit;
            break;
        case USB_HID_KEYBOARD_KEYPAD_KEYBOARD_RIGHT_SHIFT:
            appData.keyboardModifierKeys.rightShift = modifier_bit;
            break;
        case USB_HID_KEYBOARD_KEYPAD_KEYBOARD_RIGHT_ALT:
            appData.keyboardModifierKeys.rightAlt = modifier_bit;
            break;
        case USB_HID_KEYBOARD_KEYPAD_KEYBOARD_RIGHT_GUI:
            appData.keyboardModifierKeys.rightGui = modifier_bit;
            break;
        default:
            modifier = false;
            break;
    }

    // The upper byte is not needed for now except to detect press and release.
    if ((KEY_RELEASE & code) != KEY_RELEASE ){
        if (!modifier){
            appData.key = code & 0xff;
            appData.isSwitchPressed = true;
        }
    }
}

void Translated_Command(uint8_t command, bool success, uint8_t data){
    // Dont care about commands so leaving this empty
}

USB_DEVICE_HID_EVENT_RESPONSE APP_USBDeviceHIDEventHandler
(
    USB_DEVICE_HID_INDEX hidInstance,
    USB_DEVICE_HID_EVENT event,
    void * eventData,
    uintptr_t userData
)
{
    APP_DATA * appData = (APP_DATA *)userData;

    switch(event)
    {
        case USB_DEVICE_HID_EVENT_REPORT_SENT:

            /* This means the mouse report was sent.
             We are free to send another report */

            appData->isReportSentComplete = true;
            break;

        case USB_DEVICE_HID_EVENT_REPORT_RECEIVED:

            /* This means we have received a report */
            appData->isReportReceived = true;
            break;

        case USB_DEVICE_HID_EVENT_SET_IDLE:

             /* Acknowledge the Control Write Transfer */
           USB_DEVICE_ControlStatus(appData->deviceHandle, USB_DEVICE_CONTROL_STATUS_OK);

            /* save Idle rate recieved from Host */
            appData->idleRate 
                   = ((USB_DEVICE_HID_EVENT_DATA_SET_IDLE*)eventData)->duration;
            break;

        case USB_DEVICE_HID_EVENT_GET_IDLE:

            /* Host is requesting for Idle rate. Now send the Idle rate */
            USB_DEVICE_ControlSend(appData->deviceHandle, & (appData->idleRate),1);

            /* On successfully reciveing Idle rate, the Host would acknowledge back with a
               Zero Length packet. The HID function drvier returns an event
               USB_DEVICE_HID_EVENT_CONTROL_TRANSFER_DATA_SENT to the application upon
               receiving this Zero Length packet from Host.
               USB_DEVICE_HID_EVENT_CONTROL_TRANSFER_DATA_SENT event indicates this control transfer
               event is complete */ 

            break;

        case USB_DEVICE_HID_EVENT_SET_PROTOCOL:
            /* Host is trying set protocol. Now receive the protocol and save */
            appData->activeProtocol
                = ((USB_DEVICE_HID_EVENT_DATA_SET_PROTOCOL *)eventData)->protocolCode;

              /* Acknowledge the Control Write Transfer */
            USB_DEVICE_ControlStatus(appData->deviceHandle, USB_DEVICE_CONTROL_STATUS_OK);
            break;

        case  USB_DEVICE_HID_EVENT_GET_PROTOCOL:

            /* Host is requesting for Current Protocol. Now send the Idle rate */
             USB_DEVICE_ControlSend(appData->deviceHandle, &(appData->activeProtocol), 1);

             /* On successfully reciveing Idle rate, the Host would acknowledge
               back with a Zero Length packet. The HID function drvier returns
               an event USB_DEVICE_HID_EVENT_CONTROL_TRANSFER_DATA_SENT to the
               application upon receiving this Zero Length packet from Host.
               USB_DEVICE_HID_EVENT_CONTROL_TRANSFER_DATA_SENT event indicates
               this control transfer event is complete */
             break;

        case USB_DEVICE_HID_EVENT_CONTROL_TRANSFER_DATA_SENT:
            break;

        default:
            break;
    }

    return USB_DEVICE_HID_EVENT_RESPONSE_NONE;
}

/*******************************************************************************
  Function:
    void APP_USBDeviceEventHandler (USB_DEVICE_EVENT event,
        USB_DEVICE_EVENT_DATA * eventData)

  Summary:
    Event callback generated by USB device layer.

  Description:
    This event handler will handle all device layer events.

  Parameters:
    None.

  Returns:
    None.
 */

void APP_USBDeviceEventHandler(USB_DEVICE_EVENT event,
        void * eventData, uintptr_t context)
{
    USB_DEVICE_EVENT_DATA_CONFIGURED *configurationValue;


    switch(event)
    {
        case USB_DEVICE_EVENT_SOF:
            /* This event is used for switch debounce. This flag is reset
             * by the switch process routine. */
            appData.sofEventHasOccurred = true;
            break;
        case USB_DEVICE_EVENT_RESET:
        case USB_DEVICE_EVENT_DECONFIGURED:

            /* Device got deconfigured */

            appData.isConfigured = false;
            appData.state = APP_STATE_WAIT_FOR_CONFIGURATION;
            BSP_LEDOn (APP_USB_LED_1);
            BSP_LEDOn (APP_USB_LED_2);
            BSP_LEDOff (APP_USB_LED_3);

            break;

        case USB_DEVICE_EVENT_CONFIGURED:

            /* Device is configured */

            configurationValue = (USB_DEVICE_EVENT_DATA_CONFIGURED *)eventData;
            if(configurationValue->configurationValue == 1)
            {
                appData.isConfigured = true;

                BSP_LEDOff ( APP_USB_LED_1 );
                BSP_LEDOff ( APP_USB_LED_2 );
                BSP_LEDOn ( APP_USB_LED_3 );

                /* Register the Application HID Event Handler. */

                USB_DEVICE_HID_EventHandlerSet(appData.hidInstance,
                        APP_USBDeviceHIDEventHandler, (uintptr_t)&appData);
            }
            break;

        case USB_DEVICE_EVENT_SUSPENDED:
            BSP_LEDOff ( APP_USB_LED_1 );
            BSP_LEDOn ( APP_USB_LED_2 );
            BSP_LEDOn ( APP_USB_LED_3 );
            break;

        case USB_DEVICE_EVENT_RESUMED:
        case USB_DEVICE_EVENT_POWER_DETECTED:
            /* Attach the device */
            USB_DEVICE_Attach (appData.deviceHandle);
            break;
        case USB_DEVICE_EVENT_POWER_REMOVED:
            /* There is no VBUS. We can detach the device */
            USB_DEVICE_Detach(appData.deviceHandle);
            break;
        case USB_DEVICE_EVENT_ERROR:
        default:
            break;

    }
}


// *****************************************************************************
// *****************************************************************************
// Section: Application Local Functions
// *****************************************************************************
// *****************************************************************************

/********************************************************
 * Application switch press routine
 ********************************************************/

void APP_ProcessSwitchPress(void)
{
    /* This function checks if the switch is pressed and then
     * debounces the switch press*/

/* Check if a key was pressed */
    if(BSP_SWITCH_STATE_PRESSED == (BSP_SwitchStateGet(APP_USB_SWITCH_1)))
    {
        if(appData.ignoreSwitchPress)
        {
            /* This measn the key press is in progress */
            if(appData.sofEventHasOccurred)
            {
                /* A timer event has occurred. Update the debounce timer */
                appData.switchDebounceTimer ++;
                appData.sofEventHasOccurred = false;
                if(appData.switchDebounceTimer == APP_USB_SWITCH_DEBOUNCE_COUNT)
                {
                    /* Indicate that we have valid switch press. The switch is
                     * pressed flag will be cleared by the application tasks
                     * routine. We should be ready for the next key press.*/
                    appData.isSwitchPressed = true;
                    appData.switchDebounceTimer = 0;
                    appData.ignoreSwitchPress = false;
                }
            }
        }
        else
        {
            /* We have a fresh key press */
            appData.ignoreSwitchPress = true;
            appData.switchDebounceTimer = 0;
        }
    }
    else
    {
        /* No key press. Reset all the indicators. */
        appData.ignoreSwitchPress = false;
        appData.switchDebounceTimer = 0;
        appData.sofEventHasOccurred = false;
    }
}

/********************************************************
 * Application Keyboard LED update routine.
 ********************************************************/

void APP_KeyboardLEDStatus(void)
{
    /* This measn we have a valid output report from the host*/

    if(keyboardOutputReport.ledState.numLock
            == KEYBOARD_LED_STATE_ON)
    {
        //BSP_LEDOn(APP_USB_LED_2);
        appData.keyboard_LED |= PS2K_NUM_LOCK;
    }
    else
    {
        //BSP_LEDOff(APP_USB_LED_2);
        appData.keyboard_LED &= ~PS2K_NUM_LOCK;

    }

    if(keyboardOutputReport.ledState.capsLock
            == KEYBOARD_LED_STATE_ON)
    {
        //BSP_LEDOn(APP_USB_LED_1);
        appData.keyboard_LED |= PS2K_CAPS_LOCK;
    }
    else
    {
        //BSP_LEDOff(APP_USB_LED_1);
        appData.keyboard_LED &= ~PS2K_CAPS_LOCK;
    }

    if(keyboardOutputReport.ledState.scrollLock
            == KEYBOARD_LED_STATE_ON)
    {
        //BSP_LEDOn(APP_USB_LED_1);
        appData.keyboard_LED |= PS2K_SCRL_LOCK;
    }
    else
    {
        //BSP_LEDOff(APP_USB_LED_1);
        appData.keyboard_LED &= ~PS2K_SCRL_LOCK;
    }
    
    PS2K_SetLED(appData.keyboard_LED);
}

/********************************************************
 * Application Keyboard Emulation Routine
 ********************************************************/

void APP_EmulateKeyboard(void)
{

    if(appData.isSwitchPressed)
    {
        /* Clear the switch pressed flag */
        appData.isSwitchPressed = false;

        /* If the switch was pressed, update the key counter and then
         * add the key to the keycode array. */
        /*
         appData.key ++;

        if(appData.key == USB_HID_KEYBOARD_KEYPAD_KEYBOARD_RETURN_ENTER)
        {
            appData.key = USB_HID_KEYBOARD_KEYPAD_KEYBOARD_A;
        }
        */

        appData.keyCodeArray.keyCode[0] = appData.key;


        /* Start a switch press ignore counter */
    }
    else
    {
        /* Indicate no event */

         appData.keyCodeArray.keyCode[0] =
                 USB_HID_KEYBOARD_KEYPAD_RESERVED_NO_EVENT_INDICATED;
    }

    KEYBOARD_InputReportCreate(&appData.keyCodeArray,
            &appData.keyboardModifierKeys, &keyboardInputReport);

}

/**********************************************
 * This function is called by when the device
 * is de-configured. It resets the application
 * state in anticipation for the next device
 * configured event
 **********************************************/

void APP_StateReset(void)
{
    appData.isReportReceived = false;
    appData.isReportSentComplete = true;
    appData.key = USB_HID_KEYBOARD_KEYPAD_KEYBOARD_A;
    appData.keyboardModifierKeys.modifierkeys = 0;
    keyboardOutputReport.data = 0;
    appData.isSwitchPressed = false;
    appData.ignoreSwitchPress = false;
}


// *****************************************************************************
// *****************************************************************************
// Section: Application Initialization and State Machine Functions
// *****************************************************************************
// *****************************************************************************

/*******************************************************************************
  Function:
    void APP_Initialize ( void )

  Remarks:
    See prototype in app.h.
 */

void APP_Initialize ( void )
{
    /* Place the App state machine in its initial state. */
    appData.state = APP_STATE_INIT;
    
    appData.deviceHandle = USB_DEVICE_HANDLE_INVALID;
    appData.isConfigured = false;

    /* Initialize the keycode array */
    appData.key = USB_HID_KEYBOARD_KEYPAD_KEYBOARD_A;
    appData.keyCodeArray.keyCode[0] = USB_HID_KEYBOARD_KEYPAD_RESERVED_NO_EVENT_INDICATED;
    appData.keyCodeArray.keyCode[1] = USB_HID_KEYBOARD_KEYPAD_RESERVED_NO_EVENT_INDICATED;
    appData.keyCodeArray.keyCode[2] = USB_HID_KEYBOARD_KEYPAD_RESERVED_NO_EVENT_INDICATED;
    appData.keyCodeArray.keyCode[3] = USB_HID_KEYBOARD_KEYPAD_RESERVED_NO_EVENT_INDICATED;
    appData.keyCodeArray.keyCode[4] = USB_HID_KEYBOARD_KEYPAD_RESERVED_NO_EVENT_INDICATED;
    appData.keyCodeArray.keyCode[5] = USB_HID_KEYBOARD_KEYPAD_RESERVED_NO_EVENT_INDICATED;
    
    /* Initialize the modifier keys */
    appData.keyboardModifierKeys.modifierkeys = 0;

    /* Initialise the led state */
    keyboardOutputReport.data = 0;

    /* Initialize the switch state */
    appData.isSwitchPressed = false;
    appData.ignoreSwitchPress = false;

    /* Initialize the HID instance index.  */
    appData.hidInstance = 0;

    /* Initialize tracking variables */
    appData.isReportReceived = false;
    appData.isReportSentComplete = true;

    appData.keyboard_id = 0;
    appData.keyboard_LED = 0;

}


/******************************************************************************
  Function:
    void APP_Tasks ( void )

  Remarks:
    See prototype in app.h.
 */

void APP_Tasks ( void )
{
    /* Check the application's current state. */
    switch ( appData.state )
    {
        /* Application's initial state. */
        case APP_STATE_INIT:
        {
            // ** PS2 init section
            // Init PS2
            PS2K_Init();
            // Init translator
            TranslatorInit();

            appData.keyboard_id = 1;
            appData.keyboard_id = BeginKeyTranslationMatrix(appData.keyboard_id, 104);
            TranslatorCallback(appData.keyboard_id,Translated_Key,Translated_Command);

            int index;
            int size = sizeof(americanKeyboard) / 8;
            int offset;
            for (index = 0; index < size; index++){
                for (offset = 0; offset < 8; offset++){
                    AddKeyTranslationMatrix(americanKeyboard[index * 8 + offset]);
                }
            }

            PS2K_Callback(PS2_Keyboard_Int);
            PS2K_ResetKeyboard();

            // ** End PS2 init section

		    /* Open the device layer */
            appData.deviceHandle = USB_DEVICE_Open( USB_DEVICE_INDEX_0,
                    DRV_IO_INTENT_READWRITE );

            if(appData.deviceHandle != USB_DEVICE_HANDLE_INVALID)
            {
                /* Register a callback with device layer to get event notification (for end point 0) */
                USB_DEVICE_EventHandlerSet(appData.deviceHandle,
                        APP_USBDeviceEventHandler, 0);

                appData.state = APP_STATE_WAIT_FOR_CONFIGURATION;
            }
            else
            {
                /* The Device Layer is not ready to be opened. We should try
                 * again later. */
            }
            break;
        }

        case APP_STATE_WAIT_FOR_CONFIGURATION:

            /* Check if the device is configured. The
             * isConfigured flag is updated in the
             * Device Event Handler */

            if(appData.isConfigured)
            {
                /* Initialize the flag and place a request for a
                 * output report */

                appData.isReportReceived = false;

                USB_DEVICE_HID_ReportReceive(appData.hidInstance,
                        &appData.receiveTransferHandle,
                        (uint8_t *)&keyboardOutputReport,1);

                appData.state = APP_STATE_CHECK_IF_CONFIGURED;
            }

            break;

        case APP_STATE_CHECK_IF_CONFIGURED:

            /* This state is needed because the device can get
             * unconfigured asynchronously. Any application state
             * machine reset should happen within the state machine
             * context only. */

            if(appData.isConfigured)
            {
                appData.state = APP_STATE_SWITCH_PROCESS;
            }
            else
            {
                /* This means the device got de-configured.
                 * We reset the state and the wait for configuration */

                APP_StateReset();
                appData.state = APP_STATE_WAIT_FOR_CONFIGURATION;
            }
            break;

        case APP_STATE_SWITCH_PROCESS:
            
            /* Process the switch state and go to the
             * next state. */
            
            APP_ProcessSwitchPress();
            appData.state = APP_STATE_CHECK_FOR_OUTPUT_REPORT;
            break;

        case APP_STATE_CHECK_FOR_OUTPUT_REPORT:

            if(appData.isReportReceived == true)
            {
                /* Update the LED and schedule and
                 * request */

                APP_KeyboardLEDStatus();

                appData.isReportReceived = false;
                USB_DEVICE_HID_ReportReceive(appData.hidInstance,
                        &appData.receiveTransferHandle,
                        (uint8_t *)&keyboardOutputReport,1);
            }

            appData.state = APP_STATE_EMULATE_KEYBOARD;
            break;

        case APP_STATE_EMULATE_KEYBOARD:

            if(appData.isReportSentComplete)
            {
                /* This means report can be sent*/
                
                APP_EmulateKeyboard();
                
                appData.isReportSentComplete = false;
                USB_DEVICE_HID_ReportSend(appData.hidInstance,
                    &appData.sendTransferHandle,
                    (uint8_t *)&keyboardInputReport,
                    sizeof(KEYBOARD_INPUT_REPORT));
             }

            appData.state = APP_STATE_CHECK_IF_CONFIGURED;
            break;

        case APP_STATE_ERROR:
            break;

        /* The default state should never be executed. */
        default:
        {
            /* TODO: Handle error in application's state machine. */
            break;
        }
    }
}
 

/*******************************************************************************
 End of File
 */

